<?php

namespace addons\yunfood\controller;

use addons\yunfood\library\Logic;
use addons\yunfood\library\Super;
use addons\yunfood\model\FoodSku;
use addons\yunfood\model\FundRecord;
use addons\yunfood\model\FundUser;
use addons\yunfood\model\OrderInvoice;
use addons\yunfood\model\OrderItem;
use addons\yunfood\model\OrderRefund;
use addons\yunfood\model\Payment;
use addons\yunfood\model\Food;
use addons\yunfood\model\Cart;
use addons\yunfood\model\Order as OrderModel;
use addons\yunfood\model\Shop;
use addons\yunfood\model\ShopDesk;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\Validate;

/**
 * 订单接口
 */
class Order extends BaseApi
{
    // 加入购物车
    public function addCart()
    {
        // 参数校验
        $data = $this->request->post();
        $validate = new Validate([
            'goods_id'    => 'require',
            'goods_count' => 'require'
        ]);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }

        // 校验门店
        $this->validShop();

        $goodsId = $data['goods_id'];
        $goodsCount = $data['goods_count'];
        $goodsData = $data['goods_data'] ?? null;

        // 购物车
        $goodsAlias = Cart::getGoodsAlias($goodsId, $goodsData);
        $cart = Cart::get(['shop_id' => $this->shopId, 'user_id' => $this->userId, 'goods_alias' => $goodsAlias]);
        if (! $cart) {
            $cart = new Cart();
            $cart->shop_id = $this->shopId;
            $cart->user_id = $this->userId;
            $cart->goods_alias = $goodsAlias;
            $cart->goods_id = $goodsId;
            $cart->goods_count = $goodsCount;
        } else {
            $cart->goods_count += $goodsCount;
        }
        $cart->goods_data = json_encode($goodsData);

        // 校验菜品
        [$goodsName, $goodsCover, $goodsPrice, $goodsSkuId] = $this->validFoodState($goodsId,
            $goodsData, $cart->goods_count);
        $cart->goods_name = $goodsName;
        $cart->goods_cover = $goodsCover;
        $cart->goods_price = $goodsPrice;
        $cart->goods_sku_id = $goodsSkuId;
        $cart->save();

        $this->success('success', Super::arrayGetSet($cart, [
            'id',
            'goods_alias',
            'goods_id',
            'goods_name',
            'goods_names',
            'goods_cover',
            'goods_price',
            'goods_data' => function ($item) {
                return json_decode($item->goods_data, true);
            },
            'goods_count'
        ]));
    }

    // 操作购物车
    public function handleCart()
    {
        // 参数校验
        $data = $this->request->post();
        $validate = new Validate([
            'cart_id' => 'require',
            'action'  => 'require',
        ]);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }
        $cartId = $this->request->post('cart_id');
        if ($cart = Cart::get(['id' => $cartId, 'user_id' => $this->userId])) {
            if ($data['action'] === 'increase') {
                // 校验菜品
                $this->validFoodState($cart->goods_id, json_decode($cart->goods_data, true), ++$cart->goods_count);
                Cart::where('id', $cart->id)->update([
                    'goods_count' => Db::raw('goods_count+1'),
                ]);
            } elseif ($data['action'] === 'decrease') {
                if ($cart->goods_count <= 1) {
                    $cart->delete();
                } else {
                    Cart::where('id', $cart->id)->update([
                        'goods_count' => Db::raw('goods_count-1'),
                    ]);
                }
            } elseif ($data['action'] === 'delete') {
                $cart->delete();
            }
        }

        $this->success('success');
    }

    private function validFoodState($goodsId, $goodsData, $goodsCount)
    {
        if (! $food = Food::get($goodsId)) {
            $this->error('菜品不存在');
        }
        if ($food->status != Food::STATUS_NORMAL) {
            $this->error('菜品已下架');
        }
        if ($food->count_left < $goodsCount) {
            $this->error('菜品库存不够');
        }
        if ($food->shop_ids) {
            if (! in_array($this->shopId, explode(',', $food->shop_ids))) {
                $this->error('当前门店没有此菜品');
            }
        }
        $goodsName = $food['name'];
        $goodsCover = $food->cover_url;
        $goodsPrice = $food->price;
        $goodsSkuId = 0;

        // 规格和加菜
        if ($goodsData) {
            if ($specData = $goodsData['spec_data'] ?? null) {
                if (! $foodSku = FoodSku::get($specData['id'])) {
                    $this->error('菜品规格不存在');
                }
                if ($foodSku->status != FoodSku::STATUS_NORMAL) {
                    $this->error('菜品规格已下架');
                }
                if ($foodSku->count_left < $goodsCount) {
                    $this->error('菜品规格库存不够');
                }
                $goodsSkuId = $foodSku->id;
                if ($foodSku->cover_url) {
                    $goodsCover = $foodSku->cover_url;
                }
                $goodsPrice = $foodSku->price;
            }
            if ($addonList = $goodsData['addon_list'] ?? []) {
                $addonMap = array_column($addonList, null, 'id');
                $addonIds = array_keys($addonMap);
                $foodList = Food::where('id', 'in', $addonIds)->where('multi_spec', 0)->show()->select();
                if (count($foodList) != count($addonList)) {
                    $this->error('加菜数据有误');
                }
                foreach ($foodList as $item) {
                    $addonInfo = $addonMap[$item->id];
                    if ($item->count_left < $goodsCount) {
                        $this->error('加菜"' . $item->name . '"库存不够');
                    }
                    $goodsPrice += $item->price;
                }
            }
        }

        return [$goodsName, $goodsCover, $goodsPrice, $goodsSkuId];
    }

    // 清空购物车
    public function emptyCart()
    {
        Cart::destroy(['user_id' => $this->userId]);

        $this->success('success');
    }

    // 获取购物车列表
    public function getCartList()
    {
        $result = Cart::getCartList($this->userId, $this->shopId);

        $this->success('success', $result);
    }

    // 预览订单
    public function previewOrder()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'goods_list' => 'require',
        ]);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }

        // 校验门店
        $this->validShop();

        $goodsList = $data['goods_list'];

        // 订单数据
        $totalPrice = $totalDiscount = $totalPayment = $orderItems = null;
        try {
            list($totalPrice, $totalDiscount, $totalPayment, $orderItems) = $this->generateOrderData($goodsList);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }

        // 门店数据
        if ($shopData = Shop::get($data['shop_id'])) {
            $shopData = Super::arrayGetSet($shopData, [
                'id',
                'name',
                'cover_url',
                'address',
                'state'
            ]);
        }

        // 桌号数据
        if ($deskData = empty($data['desk_id']) ? null : ShopDesk::get($data['desk_id'])) {
            $deskData = Super::arrayGetSet($deskData, [
                'id',
                'number',
            ]);
        }

        $result = [
            'shop_data'      => $shopData,
            'desk_data'      => $deskData,
            'goods_list'     => $orderItems,
            'total_price'    => $totalPrice,
            'total_discount' => $totalDiscount,
            'total_payment'  => $totalPayment
        ];
        $fundUser = FundUser::get(['user_id' => $this->userId]);
        $result['fund_account_status'] = $fundUser->status ?? 0;
        $result['fund_amount_left'] = $fundUser->amount_left ?? 0;
        $result['subscribe_template_ids'] = [];
//        $result['subscribe_template_ids'] = ['Yx74Zfe8fc_8oPRZke9sHKXyWV50IT0T7NNkkns2OXo'];

        $this->success('success', $result);
    }

    // 立即下单
    public function submitOrder()
    {
        $data = $this->request->post();
        $validate = new Validate([
            'enjoy_type'    => 'require',
            'goods_list'    => 'require',
            'total_payment' => 'require',
        ]);
        if (! $validate->check($data)) {
            $this->error($validate->getError());
        }

        // 校验门店
        $this->validShop();

        $deskId = $data['desk_id'] ?? 0;
        $enjoyType = $data['enjoy_type'];
        $goodsList = $data['goods_list'];
        $userTotalPayment = $data['total_payment'];
        $useFundAmount = $data['use_fund_amount'] ?? 0;  // 使用余额支付
        $result = null;

        // 开启事务
        Db::startTrans();
        try {
            list($totalPrice, $totalDiscount, $totalPayment, $orderItems) = $this->generateOrderData($goodsList);
            if ($totalPayment <= 0) {
                throw new Exception('价格有变，请重新下单');
            }
            $orderNo = Logic::generateBusinessNo('order_no');

            // 扣除账户余额
            $balanceAmount = 0;
            if ($useFundAmount && $totalPayment > 0) {
                $balanceAmount = FundUser::amountCounter($this->userId, FundRecord::ACTION_CONSUME, -$totalPayment,
                    true, FundRecord::SOURCE_TYPE_ORDER, $orderNo);
                if ($balanceAmount > 0) {
                    OrderItem::scaleOrderItemBalance($orderItems, $balanceAmount, $totalPayment);
                }
            }
            if ($userTotalPayment != $totalPayment) {
                throw new Exception('价格有变，请重新下单');
            }

            // 订单数据
            $order = new OrderModel();
            $order->order_no = $orderNo;
            $order->order_type = OrderModel::ORDER_TYPE_DEFAULT;
            $order->shop_id = $this->shopId;
            $order->desk_id = $deskId;
            $order->enjoy_type = $enjoyType;
            $order->contact = $data['contact'] ?? '';
            $order->user_id = $this->userId;
            $order->user_data = null;
            $order->total_price = $totalPrice;
            $order->discount = $totalDiscount;
            $order->payment = $totalPayment;
            $order->balance = $balanceAmount;
            if ($totalPayment - $balanceAmount > 0) {
                $order->payment_status = OrderModel::PAYMENT_STATUS_WAIT;
                $order->status = OrderModel::STATUS_WAIT_PAY;
            } else {
                $order->payment_time = time();
                $order->payment_status = OrderModel::PAYMENT_STATUS_DONE;
                $order->status = OrderModel::STATUS_HAS_FINISH;
            }
            $order->refund_status = OrderModel::REFUND_STATUS_NO;
            $order->invoice_status = OrderModel::INVOICE_STATUS_NO;
            $order->save();


            // 订单商品
            $cartIds = [];
            foreach ($orderItems as $key => &$item) {
                $item['order_no'] = $order->order_no;
                $item['order_item_no'] = $order->order_no . str_pad($key, 2, '0', STR_PAD_LEFT);
                $item['refund_status'] = OrderItem::REFUND_STATUS_NO;
                $item['goods_data'] = $item['goods_data'] ? json_encode($item['goods_data']) : null;
                if (! empty($item['cart_id'])) {
                    $cartIds[] = $item['cart_id'];
                }
                Food::where('id', $item['goods_id'])->dec('count_left', $item['goods_count'])->update();
                if ($goodsData = $item['goods_data']) {
                    if ($specData = $goodsData['spec_data'] ?? null) {
                        FoodSku::where('id', $specData['id'])->dec('count_left', $item->goods_count)->update();
                    }
                    if ($addonList = $goodsData['addon_list'] ?? null) {
                        foreach ($addonList as $addon) {
                            Food::where('id', $addon['id'])->dec('count_left')->update();
                        }
                    }
                }
            }
            $orderItem = new OrderItem();
            $orderItem->allowField(true)->saveAll($orderItems);

            // 无需支付
            if ($order->payment_status == OrderModel::PAYMENT_STATUS_DONE) {
                OrderModel::finishOrder($order->order_no, 0, '余额支付');
            }

            // 清理购物车
            if ($cartIds) {
                Cart::destroy($cartIds);
            }

            $result = Super::arrayGetSet($order, ['order_no', 'payment_status']);
            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success', $result);
    }

    private function generateOrderData($goodsList = [])
    {
        if (count($goodsList) >= 100) {
            throw new Exception('一次性下单不能超过100种菜品');
        }
        $totalPrice = 0;
        $totalDiscount = 0;
        $totalPayment = 0;
        $orderItems = [];
        foreach ($goodsList as $goods) {
            if (! $food = Food::get($goods['goods_id'])) {
                throw new Exception('菜品"' . $goods['goods_name'] . '"不存在');
            }
            if ($food->state == Food::STATE_OFF) {
                throw new Exception('菜品"' . $food['name'] . '"已下架');
            }
            if ($food->state == Food::STATE_OUT) {
                throw new Exception('菜品"' . $food['name'] . '"已售罄');
            }
            if ($food->count_left < $goods['goods_count']) {
                throw new Exception('菜品"' . $food['name'] . '"库存不够');
            }
            if ($food->shop_ids) {
                if (! in_array($this->shopId, explode(',', $food->shop_ids))) {
                    throw new Exception('当前门店没有菜品"' . $food['name'] . '"');
                }
            }
            $goodsData = $goods['goods_data'] ?? [];
            $specData = $goodsData['spec_data'] ?? null;
            if ($specData) {
                if (! $foodSku = FoodSku::get($specData['id'])) {
                    throw new Exception('菜品"' . $food['name'] . '的规格"' . $foodSku['spec_text'] . '"不存在');
                }
                if ($foodSku->state == FoodSku::STATE_OFF) {
                    throw new Exception('菜品"' . $food['name'] . '的规格"' . $foodSku['spec_text'] . '"已下架');
                }
                if ($foodSku->state == FoodSku::STATE_OUT) {
                    throw new Exception('菜品"' . $food['name'] . '的规格"' . $foodSku['spec_text'] . '"已售罄');
                }
                if ($foodSku->count_left < $goods['goods_count']) {
                    throw new Exception('菜品"' . $food['name'] . '的规格"' . $foodSku['spec_text'] . '"库存不够');
                }
                $price = $foodSku->market_price;
                $payment = $foodSku->price;
                $discount = $price - $payment;
            } else {
                if ($food->multi_spec) {
                    throw new Exception('菜品"' . $food['name'] . '"没有选择规格');
                }
                $price = $food->market_price;
                $payment = $food->price;
                $discount = $price - $payment;
            }
            if ($addonList = $goodsData['addon_list'] ?? []) {
                $addonMap = array_column($addonList, null, 'id');
                $addonIds = array_keys($addonMap);
                $foodList = Food::where('id', 'in', $addonIds)->where('multi_spec', 0)->show()->select();
                if (count($foodList) != count($addonList)) {
                    throw new Exception('菜品"' . $food['name'] . '"加菜数据有误');
                }
                foreach ($foodList as $tItem) {
                    $addonInfo = $addonMap[$tItem->id];
                    if ($tItem->count_left < ($addonInfo['count'] ?? 0)) {
                        throw new Exception('菜品"' . $food['name'] . '"加菜' . $tItem->name . '"已卖完');
                    }
                    $price += $tItem->market_price;
                    $discount += $tItem->market_price - $tItem->price;
                    $payment += $tItem->price;
                }
            }
            $price = $price * $goods['goods_count'];
            $payment = $payment * $goods['goods_count'];
            $discount = $discount * $goods['goods_count'];

            $orderItems[] = Super::arrayGetSet($food, [
                'cart_id'     => function ($item) use ($goods) {
                    return $goods['cart_id'] ?? 0;
                },
                'goods_id'    => 'id',
                'goods_type'  => function ($item) {
                    return 'food';
                },
                'goods_name'  => 'name',
                'goods_names' => function ($item) use ($goods) {
                    return Logic::getGoodsNames($goods['goods_data']);
                },
                'goods_cover' => 'cover_url',
                'goods_price' => 'price',
                'goods_data'  => function ($item) use ($goods) {
                    return $goods['goods_data'];
                },
                'goods_count' => function ($item) use ($goods) {
                    return $goods['goods_count'];
                },
                'payment'     => function ($item) use ($payment) {
                    return $payment;
                }
            ]);
            $totalPrice = bcadd($totalPrice, $price, 2);
            $totalDiscount = bcadd($totalDiscount, $discount, 2);
            $totalPayment = bcadd($totalPayment, $payment, 2);
        }

        // TODO：整单优惠
        $wholeDiscount = 0;
        if ($wholeDiscount > 0) {
            OrderItem::scaleOrderItemPayment($orderItems, $wholeDiscount, $totalPayment);
            $totalDiscount += $wholeDiscount;
            $totalPayment -= $wholeDiscount;
        }

        return [$totalPrice, $totalDiscount, $totalPayment, $orderItems];
    }

    // 立即支付
    public function oncePay()
    {
        $orderNo = $this->request->post('order_no');
        $channel = $this->request->post('channel');
        $result = null;

        // 开启事务
        Db::startTrans();
        try {
            if (! $order = OrderModel::where([
                'user_id'  => $this->userId,
                'order_no' => $orderNo
            ])->lock(true)->find()) {
                throw new Exception('订单不存在');
            }
            if ($order->status != OrderModel::STATUS_WAIT_PAY) {
                throw new Exception('订单无效');
            }
            if ($order->created_at < time() - 86400) {
                $order->status = OrderModel::STATUS_HAS_TIMEOUT;
                $order->save();
                Db::commit();
                throw new Exception('超时结束');
            }

            // 支付数据
            $payment = Payment::getPaymentData(Payment::ORDER_TYPE_GOODS, $order, $channel);
            if (! $payment) {
                throw new Exception('获取支付数据失败');
            }

            // 保存订单
            $order->payment_no = $payment->payment_no;
            $order->payment_status = OrderModel::PAYMENT_STATUS_WAIT;
            $order->save();

            // 支付信息
            $result = $payment->getPaymentResult();
            Db::commit();
        } catch (PDOException | \Exception $e) {
            if ($e->getMessage() !== '超时结束') {
                Db::rollback();
            }
            $this->error($e->getMessage());
        }

        $this->success('success', $result);
    }

    // 获取订单列表
    public function getOrderList()
    {
        $group = $this->request->post('group');

        // 数据列表
        $query = OrderModel::where(['user_id' => $this->userId]);
        if ($group == 1) {
            $query->where(['status' => OrderModel::STATUS_WAIT_PAY]);
        } elseif ($group == 2) {
            $query->where(['status' => OrderModel::STATUS_HAS_FINISH]);
        } elseif ($group == 3) {
            $query->where(['status' => OrderModel::STATUS_HAS_CANCEL]);
        }
        $query->order(['id' => 'DESC']);

        $result = $query->paginate($this->request->post('page_size', 10), false);
        $result = Logic::getPageData($result, [
            'id',
            'order_no',
            'goods_list',
            'status',
            'status_text',
            'total_price',
            'discount',
            'payment',
            'balance',
            'payment_rel',
            'payment_time',
            'payment_status',
            'created_at',
        ]);

        $this->success('success', $result);
    }

    // 获取订单详情
    public function getOrderDetail()
    {
        $orderNo = $this->request->post('order_no');
        if (! $order = OrderModel::get(['user_id' => $this->userId, 'order_no' => $orderNo])) {
            $this->error('订单不存在');
        }

        $result = Super::arrayGetSet($order, [
            'id',
            'order_no',
            'goods_list',
            'shop_id',
            'shop_data' => function ($item) {
                return Super::arrayGetSet($item->shopData, [
                    'id',
                    'name',
                    'cover_url',
                    'address',
                    'state'
                ]);
            },
            'desk_id',
            'desk_data' => function ($item) {
                if (! $item->deskData) {
                    return null;
                }

                return Super::arrayGetSet($item->deskData, [
                    'id',
                    'number',
                ]);
            },
            'enjoy_type',
            'enjoy_type_text',
            'contact',
            'status',
            'status_text',
            'total_price',
            'discount',
            'payment',
            'balance',
            'payment_rel',
            'payment_time',
            'payment_name',
            'payment_status',
            'refund_no',
            'refund_status',
            'refund_status_text',
            'invoice_no',
            'invoice_status',
            'invoice_status_text',
            'created_at',
            'opt_actions'
        ]);

        $this->success('success', $result);
    }

    // 订单取消
    public function orderCancel()
    {
        $orderNo = $this->request->post('order_no');

        // 取消订单
        try {
            OrderModel::cancelOrder($orderNo);
        } catch (Exception $e) {
            $this->error(__($e->getMessage()));
        }

        $this->success('success');
    }

    // 订单删除
    public function orderDelete()
    {
        $orderNo = $this->request->post('order_no');
        if (! $order = OrderModel::get(['user_id' => $this->userId, 'order_no' => $orderNo])) {
            $this->error('订单不存在');
        }

        // 事务处理
        try {
            Db::transaction(function () use ($order) {
                // 更新订单
                $order->delete();
            });
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }

        $this->success('success');
    }

    // 申请退款
    public function applyRefund()
    {
        $orderNo = $this->request->post('order_no');
        $orderItemNo = $this->request->post('order_item_no');
        $balance = $this->request->post('balance');
        $amount = $this->request->post('amount');
        $reason = $this->request->post('reason');
        $comment = $this->request->post('comment');
        $result = null;

        // 开启事务
        Db::startTrans();
        try {
            if (! $order = OrderModel::where([
                'user_id'  => $this->userId,
                'order_no' => $orderNo
            ])->lock(true)->find()) {
                throw new Exception('订单不存在');
            }
            $data['order_amount'] = $order->payment;
            $data['refund_amount'] = $order->payment_rel;

            // 保存退款单
            $orderRefund = new OrderRefund();
            $orderRefund->refund_no = Logic::generateBusinessNo('refund_no');
            $orderRefund->user_id = $this->userId;
            $orderRefund->order_no = $orderNo;
            $orderRefund->order_item_no = $orderItemNo;
            $orderRefund->reason = $reason;
            $orderRefund->comment = $comment;

            // 更新订单商品
            if ($orderItemNo) {
                if (! $orderItem = OrderItem::where(['order_item_no' => $orderItemNo])->lock(true)->find()) {
                    throw new Exception('订单商品不存在');
                }
                if (! in_array('can_refund', $order->getOrderItemOptActions($orderItem))) {
                    throw new Exception('不能进行当前操作');
                }
                if ($orderItem->balance < $balance) {
                    throw new Exception('退款余额不能大于订单余额');
                }
                if ($orderItem->payment_rel < $amount) {
                    throw new Exception('退款金额不能大于订单金额');
                }
                $orderRefund['type'] = OrderRefund::TYPE_ORDER_ITEM;
                $orderRefund->order_balance = $orderItem->balance;
                $orderRefund->refund_balance = $balance ?: $orderItem->balance;
                $orderRefund->order_amount = $orderItem->payment_rel;
                $orderRefund->refund_amount = $amount ?: $orderItem->payment_rel;

                // 更新订单商品
                $orderItem->refund_no = $orderRefund->refund_no;
                $orderItem->refund_status = OrderItem::REFUND_STATUS_ING;
                $orderItem->save();
                // 订单退款状态
                $order->refund_status = OrderModel::REFUND_STATUS_PART;
            } else {
                if (! in_array('can_refund', $order->optActions)) {
                    throw new Exception('不能进行当前操作');
                }
                if ($order->balance < $balance) {
                    throw new Exception('退款余额不能大于订单余额');
                }
                if ($order->payment_rel < $amount) {
                    throw new Exception('退款金额不能大于订单金额');
                }
                $orderRefund['type'] = OrderRefund::TYPE_ORDER;
                $orderRefund->order_balance = $order->balance;
                $orderRefund->refund_balance = $balance ?: $order->balance;
                $orderRefund->order_amount = $order->payment_rel;
                $orderRefund->refund_amount = $amount ?: $order->payment_rel;
                // 订单退款状态
                $order->refund_no = $orderRefund->refund_no;
                $order->refund_status = OrderModel::REFUND_STATUS_ING;
            }

            // 更新订单
            $order->save();

            // 保持退款单
            $orderRefund->status = OrderRefund::STATUS_WAIT;
            $orderRefund->save();
            $result = ['refund_no' => $orderRefund->refund_no];
            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success', $result);
    }


    // 退款详情
    public function refundInfo()
    {
        $refundNo = $this->request->post('refund_no');

        if (! $refund = OrderRefund::get(['user_id' => $this->userId, 'refund_no' => $refundNo])) {
            $this->error('退款信息不存在');
        }

        $result = Super::arrayGetSet($refund, [
            'refund_no',
            'type',
            'type_text',
            'order_no',
            'order_item_no',
            'order_balance',
            'refund_balance',
            'refund_balance_rel',
            'order_amount',
            'refund_amount',
            'refund_amount_rel',
            'reason',
            'reason_text',
            'comment',
            'refund_way',
            'refund_way_text',
            'refund_photos' => 'refundPhotoList',
            'refund_note',
            'refund_time',
            'status',
            'status_text'
        ]);

        $this->success('success', $result);
    }

    // 退款取消
    public function refundCancel()
    {
        $refundNo = $this->request->post('refund_no');

        // 开启事务
        Db::startTrans();
        try {
            if (! $orderRefund = OrderRefund::where([
                'user_id'   => $this->userId,
                'refund_no' => $refundNo
            ])->lock(true)->find()) {
                throw new Exception('订单不存在');
            }
            if ($orderRefund->status != OrderRefund::STATUS_WAIT) {
                throw new Exception('订单无效');
            }

            // 更新退款单
            $orderRefund->status = OrderRefund::STATUS_CANCEL;
            $orderRefund->save();

            // 订单退款状态
            if (! $order = OrderModel::where(['order_no' => $orderRefund->order_no])->lock(true)->find()) {
                throw new Exception('订单不存在');
            }

            // 订单商品退款状态
            if ($orderRefund->order_item_no) {
                if (! $orderItem = OrderItem::where(['order_item_no' => $orderRefund->order_item_no])->lock(true)->find()) {
                    throw new Exception('订单商品不存在');
                }
                // 更新订单商品
                $orderItem->refund_no = null;
                $orderItem->refund_status = OrderItem::REFUND_STATUS_NO;
                $orderItem->save();
            }

            // 更新订单
            if ($order->refund_status != OrderModel::REFUND_STATUS_PART) {
                $order->refund_no = null;
            }
            $orderItemList = $order->orderItemListData;
            $partRefund = false;
            foreach ($orderItemList as $item) {
                if ($item->refund_status != OrderItem::REFUND_STATUS_NO) {
                    $partRefund = true;
                    break;
                }
            }
            if (! $partRefund) {
                $order->refund_status = OrderModel::REFUND_STATUS_NO;
            }
            $order->save();

            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success');
    }

    // 申请发票
    public function applyInvoice()
    {
        $orderNo = $this->request->post('order_no');
        $data = $this->request->post();
        $result = null;

        // 开启事务
        Db::startTrans();
        try {
            if (! $order = OrderModel::where([
                'user_id'  => $this->userId,
                'order_no' => $orderNo
            ])->lock(true)->find()) {
                throw new Exception('发票申请不存在');
            }
            if (! in_array('can_invoice', $order->optActions)) {
                throw new Exception('不能进行当前操作');
            }

            // 保存发票单
            $orderInvoice = new OrderInvoice();
            $orderInvoice->data($data)->allowField(true);
            $orderInvoice->invoice_no = Logic::generateBusinessNo('invoice_no');
            $orderInvoice->user_id = $this->userId;
            $orderInvoice['type'] = OrderInvoice::TYPE_NORMAL;
            $orderInvoice->order_no = $orderNo;
            $orderInvoice->order_amount = $order->payment;
            $orderInvoice->invoice_amount = $order->payment_rel;
            $orderInvoice->status = OrderInvoice::STATUS_WAIT;
            $orderInvoice->save();

            // 更新订单
            $order->invoice_no = $orderInvoice->invoice_no;
            $order->invoice_status = OrderModel::INVOICE_STATUS_ING;
            $order->save();

            $result = ['invoice_no' => $orderInvoice->invoice_no];
            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success', $result);
    }

    // 发票详情
    public function invoiceInfo()
    {
        $invoiceNo = $this->request->post('invoice_no');

        if (! $invoice = OrderInvoice::get(['user_id' => $this->userId, 'invoice_no' => $invoiceNo])) {
            $this->error('开票信息不存在');
        }

        $result = Super::arrayGetSet($invoice, [
            'invoice_no',
            'type',
            'type_text',
            'title_type',
            'title_type_text',
            'title_name',
            'tax_number',
            'comment',
            'receive_email',
            'order_amount',
            'invoice_amount',
            'invoice_note',
            'invoice_photos' => 'invoicePhotoList',
            'invoice_files'  => 'invoiceFileList',
            'invoice_time',
            'status',
            'status_text'
        ]);

        $this->success('success', $result);
    }

    // 发票取消
    public function invoiceCancel()
    {
        $invoiceNo = $this->request->post('invoice_no');
        // 开启事务
        Db::startTrans();
        try {
            if (! $orderInvoice = OrderInvoice::where([
                'user_id'    => $this->userId,
                'invoice_no' => $invoiceNo
            ])->lock(true)->find()) {
                throw new Exception('发票申请不存在');
            }
            if ($orderInvoice->status != OrderInvoice::STATUS_WAIT) {
                throw new Exception('订单无效');
            }

            // 更新退款单
            $orderInvoice->status = OrderInvoice::STATUS_CANCEL;
            $orderInvoice->save();

            // 订单退款状态
            if (! $order = OrderModel::where(['order_no' => $orderInvoice->order_no])->lock(true)->find()) {
                throw new Exception('订单不存在');
            }

            // 更新订单
            $order->invoice_no = null;
            $order->invoice_status = 0;
            $order->save();

            Db::commit();
        } catch (PDOException | Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('success');
    }
}
